package com.kun.companion.core.ui.progress;

/**
 * TODO
 *
 * @author gzc
 * @since 2025/2/9 13:58
 **/

import com.kun.companion.core.ui.KunComponent;
import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.paint.*;
import javafx.util.Duration;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

/**
 * 高性能可扩展进度条基类，支持平滑动画和自定义渲染策略
 * 如果需要更复杂的样式（如动态效果、阴影等），可以通过实现 {@link RenderStrategy} 接口来自定义渲染逻辑。
 *
 * @author gzc
 */
public class BaseProgressBar extends ProgressBar implements KunComponent {
    /**
     * 动画持续时间（毫秒），设置为 0 表示无动画
     */
    private final Duration ANIMATION_DURATION = Duration.millis(0);
    /**
     * 默认插值器，用于控制动画过渡效果
     */
    private final Interpolator DEFAULT_INTERPOLATOR = Interpolator.EASE_BOTH;
    /**
     * 当前动画对象，用于管理进度条的动画
     */
    protected Transition currentAnimation;
    /**
     * 填充颜色或渐变
     */
    protected Paint fillPaint;
    /**
     * 渲染策略接口，用于自定义绘制逻辑
     */
    protected RenderStrategy renderStrategy;
    /**
     * 进度条文字
     */
    protected Label progressLabel;

    /**
     * 基础构造器
     *
     * @param initialProgress 初始进度值 (0.0-1.0)
     * @param renderStrategy  自定义渲染策略
     */
    protected BaseProgressBar(double initialProgress, Label progressLabel, RenderStrategy renderStrategy) {
        super(initialProgress);
        this.renderStrategy = renderStrategy;
        this.progressLabel = Optional.ofNullable(progressLabel).orElse(new Label());
        // 初始化样式
        initializeBaseStyle();
        // 设置动画系统
        setupAnimation();
    }

    /**
     * 初始化基础样式
     */
    private void initializeBaseStyle() {
        // 添加样式类，便于通过 CSS 自定义外观
        getStyleClass().add("kun-progress-bar");
    }

    /**
     * 配置动画系统
     * <p>
     * 监听进度变化并触发平滑动画。
     */
    private void setupAnimation() {
        progressProperty().addListener((obs, oldVal, newVal) -> {
            int intValue = BigDecimal.valueOf(newVal.doubleValue()).multiply(BigDecimal.valueOf(100))
                    .setScale(0, RoundingMode.HALF_UP).intValue();
            progressLabel.setText(intValue + "%");
            // 如果当前有动画正在运行，则停止它
            if (currentAnimation != null) {
                currentAnimation.stop();
            }
            // 创建新的动画
            currentAnimation = new Transition() {
                {
                    // 设置动画持续时间
                    setCycleDuration(ANIMATION_DURATION);
                    // 设置插值器
                    setInterpolator(DEFAULT_INTERPOLATOR);
                }

                @Override
                protected void interpolate(double frac) {
                    // 根据插值计算当前进度值
                    setProgress(interpolateProgress(oldVal.doubleValue(), newVal.doubleValue(), frac));
                }
            };
            // 播放动画
            currentAnimation.play();
        });
    }

    /**
     * 插值计算进度值
     *
     * @param start    起始进度值
     * @param end      结束进度值
     * @param fraction 插值因子 (0.0-1.0)
     * @return 插值后的进度值
     */
    private double interpolateProgress(double start, double end, double fraction) {
        return start + (end - start) * fraction;
    }

    /**
     * 自定义绘制实现
     * <p>
     * 在此方法中，根据当前进度值和渲染策略绘制进度条。
     */
    @Override
    protected void layoutChildren() {
        super.layoutChildren();
        // 创建 Canvas 用于绘制
        Canvas canvas = new Canvas(getWidth(), getHeight());
        GraphicsContext gc = canvas.getGraphicsContext2D();
        // 应用自定义渲染策略
        if (renderStrategy != null) {
            renderStrategy.render(canvas, getWidth(), getHeight(), getProgress());
        } else {
            // 使用默认渲染逻辑
            renderDefault(gc, getWidth(), getHeight());
        }
        // 将 Canvas 添加到场景图中
        getChildren().setAll(canvas);
    }

    /**
     * 设置渲染策略
     *
     * @param renderStrategy 渲染策略实现
     */
    public void setRenderStrategy(RenderStrategy renderStrategy) {
        this.renderStrategy = renderStrategy;
    }

    /**
     * 设置进度条文本
     */
    public void setProgressLabel(Label progressLabel) {
        this.progressLabel = progressLabel;
    }

    /**
     * 更新填充颜色渐变
     *
     * @param startColor 起始颜色
     * @param endColor   结束颜色
     */
    public void updateGradient(Color startColor, Color endColor) {
        // 创建线性渐变，渐变方向从左到右，平铺模式，起始颜色，结束颜色
        this.fillPaint = new LinearGradient(
                0, 0, 1, 0,
                true, CycleMethod.NO_CYCLE,
                new Stop(0.0, startColor),
                new Stop(1.0, endColor)
        );
        // 请求重新布局以应用新渐变
        requestLayout();
    }

    /**
     * 资源释放
     */
    @Override
    public void dispose() {
        styleProperty().unbind();
    }

    /**
     * 默认渲染实现
     * <p>
     * 绘制一个简单的进度条，背景为灰色，进度部分为指定颜色或渐变。
     *
     * @param gc     图形上下文
     * @param width  进度条宽度
     * @param height 进度条高度
     */
    private void renderDefault(GraphicsContext gc, double width, double height) {
        // 清除画布
        gc.clearRect(0, 0, width, height);
        // 绘制背景
        gc.setFill(Color.gray(0.9));
        // 圆角矩形
        gc.fillRoundRect(0, 0, width, height, height, height);
        // 计算进度条宽度
        double progressWidth = width * getProgress();
        // 绘制进度部分
        // 使用渐变或默认颜色
        gc.setFill(fillPaint != null ? fillPaint : Color.DODGERBLUE);
        // 圆角矩形
        gc.fillRoundRect(0, 0, progressWidth, height, height, height);
    }

    /**
     * 进度条渲染策略接口
     * <p>
     * 定义自定义渲染逻辑的接口。
     */
    public interface RenderStrategy {
        /**
         * 自定义渲染方法
         *
         * @param canvas   画布对象
         * @param width    进度条宽度
         * @param height   进度条高度
         * @param progress 当前进度值 (0.0-1.0)
         */
        void render(Canvas canvas, double width, double height, double progress);
    }


}
